<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');  
  
class Simplexml{  
  
    var $result = array();  
    var $ignore_level = 0;  
    var $skip_empty_values = false;  
    var $php_errormsg;  
    var $evalCode="";  
  
        function xml_parse($data){  
                $php_errormsg="";  
        $this->result="";  
        $this->evalCode="";  
        $values="";  
                $encoding = 'UTF-8';  
        $parser = xml_parser_create($encoding);  
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);  
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);  
        $ok = xml_parse_into_struct($parser, $data, $values);  
        if (!$ok) {  
            $errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)",  
            xml_get_error_code($parser),  
            xml_error_string(xml_get_error_code($parser)),  
            xml_get_current_line_number($parser),  
            xml_get_current_column_number($parser),  
            xml_get_current_byte_index($parser));  
        }  
  
        xml_parser_free($parser);  
        return $this->xml_reorganize($values);  
        }  
  
    function xml_reorganize($array)  
    {  
  
        $count = count($array);  
        $repeat = $this->xml_tags($array);  
        $repeatedone = false;  
        $tags = array();  
        $k = 0;  
        for ($i = 0; $i < $count; $i++) {  
            switch ($array[$i]['type']) {  
                case 'open':  
                    array_push($tags, $array[$i]['tag']);  
                    if ($i > 0 && ($array[$i]['tag'] == $array[$i-1]['tag']) && ($array[$i-1]['type'] == 'close'))  
                    $k++;  
                    if (isset($array[$i]['value']) && ($array[$i]['value'] || !$this->skip_empty_values)) {  
                        array_push($tags, '@content');  
                        $this->array_insert(count($tags), $tags, $array[$i]['value'], "open");  
                        array_pop($tags);  
                    }  
  
                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {  
                        if (($repeatedone == $array[$i]['tag'] . $array[$i]['level']) && ($repeatedone)) {  
                            array_push($tags, strval($k++));  
                        } else {  
                            $repeatedone = $array[$i]['tag'] . $array[$i]['level'];  
                            array_push($tags, strval($k));  
                        }  
                    }  
  
                    if (isset($array[$i]['attributes']) && $array[$i]['attributes'] && $array[$i]['level'] != $this->ignore_level) {  
                        array_push($tags, '@attributes');  
                        foreach ($array[$i]['attributes'] as $attrkey => $attr) {  
                            array_push($tags, $attrkey);  
                            $this->array_insert(count($tags), $tags, $attr, "open");  
                            array_pop($tags);  
                        }  
                        array_pop($tags);  
                    }  
                    break;  
  
                case 'close':  
                    array_pop($tags);  
                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {  
                        if ($repeatedone == $array[$i]['tag'] . $array[$i]['level']) {  
                            array_pop($tags);  
                        } else {  
                            $repeatedone = $array[$i + 1]['tag'] . $array[$i + 1]['level'];  
                            array_pop($tags);  
                        }  
                    }  
                    break;  
  
                case 'complete':  
                    array_push($tags, $array[$i]['tag']);  
                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {  
                        if ($repeatedone == $array[$i]['tag'] . $array[$i]['level'] && $repeatedone) {  
                            array_push($tags, strval($k));  
                        } else {  
                            $repeatedone = $array[$i]['tag'] . $array[$i]['level'];  
                            array_push($tags, strval($k));  
                        }  
                    }  
  
                    if (isset($array[$i]['value']) && ($array[$i]['value'] || !$this->skip_empty_values)) {  
                        if (isset($array[$i]['attributes']) && $array[$i]['attributes']) {  
                            array_push($tags, '@content');  
                            $this->array_insert(count($tags), $tags, $array[$i]['value'], "complete");  
                            array_pop($tags);  
                        } else {  
                            $this->array_insert(count($tags), $tags, $array[$i]['value'], "complete");  
                        }  
                    }  
  
                    if (isset($array[$i]['attributes']) && $array[$i]['attributes']) {  
                        array_push($tags, '@attributes');  
                        foreach ($array[$i]['attributes'] as $attrkey => $attr) {  
                            array_push($tags, $attrkey);  
                            $this->array_insert(count($tags), $tags, $attr, "complete");  
                            array_pop($tags);  
                        }  
                        array_pop($tags);  
                    }  
  
                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {  
                        array_pop($tags);  
                        $k++;  
                    }  
  
                    array_pop($tags);  
                    break;  
            }  
        }  
        eval($this->evalCode);  
        $last = $this->array_reindex($this->result);  
        return $last;  
    }     
  
    function array_insert($level, $tags, $value, $type)  
    {  
        $temp = '';  
        for ($c = $this->ignore_level + 1; $c < $level + 1; $c++) {  
            if (isset($tags[$c]) && (is_numeric(trim($tags[$c])) || trim($tags[$c]))) {  
                if (is_numeric($tags[$c])) {  
                    $temp .= '[' . $tags[$c] . ']';  
                } else {  
                    $temp .= '["' . $tags[$c] . '"]';  
                }  
            }  
        }  
        $this->evalCode .= '$this->result' . $temp . "=\"" . addslashes($value) . "\";//(" . $type . ")\n";  
        #echo $code. "\n";  
    }  
  
    /** 
     * Define the repeated tags in XML file so we can set an index 
     * 
     * @param array $array 
     * @return array 
     */  
    function xml_tags($array)  
    {   $repeats_temp = array();  
    $repeats_count = array();  
    $repeats = array();  
  
    if (is_array($array)) {  
        $n = count($array) - 1;  
        for ($i = 0; $i < $n; $i++) {  
            $idn = $array[$i]['tag'].$array[$i]['level'];  
            if(in_array($idn,$repeats_temp)){  
                $repeats_count[array_search($idn,$repeats_temp)]+=1;  
            }else{  
                array_push($repeats_temp,$idn);  
                $repeats_count[array_search($idn,$repeats_temp)]=1;  
            }  
        }  
    }  
    $n = count($repeats_count);  
    for($i=0;$i<$n;$i++){  
        if($repeats_count[$i]>1){  
            array_push($repeats,$repeats_temp[$i]);  
        }  
    }  
    unset($repeats_temp);  
    unset($repeats_count);  
    return array_unique($repeats);  
    }  
  
    /** 
     * Converts Array Variable to Object Variable 
     * 
     * @param array $arg_array 
     * @return $tmp 
     */  
    function array2object ($arg_array)  
    {  
  
        if (is_array($arg_array)) {  
            $keys = array_keys($arg_array);  
            if(!is_numeric($keys[0])) $tmp = new Xml;  
            foreach ($keys as $key) {  
                if (is_numeric($key)) $has_number = true;  
                if (is_string($key)) $has_string = true;  
            }  
            if (isset($has_number) and !isset($has_string)) {  
                foreach ($arg_array as $key => $value) {  
                    $tmp[] = $this->array2object($value);  
                }  
            } elseif (isset($has_string)) {  
                foreach ($arg_array as $key => $value) {  
                    if (is_string($key))  
                    $tmp->$key = $this->array2object($value);  
                }  
            }  
        } elseif (is_object($arg_array)) {  
            foreach ($arg_array as $key => $value) {  
                if (is_array($value) or is_object($value))  
                $tmp->$key = $this->array2object($value);  
                else  
                $tmp->$key = $value;  
            }  
        } else {  
            $tmp = $arg_array;  
        }  
        return $tmp; //return the object  
    }  
  
    /** 
     * Reindexes the whole array with ascending numbers 
     * 
     * @param array $array 
     * @return array 
     */  
    function array_reindex($array)  
    {  
        if (is_array($array)) {  
            if(count($array) == 1 && isset($array[0])){  
                return $this->array_reindex($array[0]);  
            }else{  
                foreach($array as $keys => $items) {  
                    if (is_array($items)) {  
                        if (is_numeric($keys)) {  
                            $array[$keys] = $this->array_reindex($items);  
                        } else {  
                            $array[$keys] = $this->array_reindex(array_merge(array(), $items));  
                        }  
                    }  
                }  
            }  
        }  
  
        return $array;  
    }  
  
}  